﻿/**
  \file memory_image.h
*/

// for including file only once
#ifndef _IMAGE_H_
#define _IMAGE_H_

/**********************
 INCLUDES
**********************/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>


/**********************
 GLOBAL DEFINES / MACROS
**********************/

/// uncomment for optional debug output (or via Makefile)
//#define MEMIMAGE_DEBUG

/// uncomment to include addresses in checksum (or via Makefile)
//#define MEMIMAGE_CHK_INCLUDE_ADDRESS

/// memory image address datatype / width
#define MEMIMAGE_ADDR_T         uint64_t

/// grow/shrink factor for memory image buffer. Must be >1.0!
#define MEMIMAGE_BUFFER_MARGIN  1.3

/// max. size for memory image buffer [B]
#define MEMIMAGE_BUFFER_MAX     50L*1024L*1024L

/// CRC32-IEEE polynom
#define CRC32_IEEE_POLYNOM      0xEDB88320

#ifdef __cplusplus
extern "C" {
#endif

/**********************
 GLOBAL STRUCTS
**********************/

/// memory entry consisting of address and data 
typedef struct _MemoryEntry_s_{
    MEMIMAGE_ADDR_T     addrStart;        //< start address
    uint8_t*             data;            //< data array
    MEMIMAGE_ADDR_T     capacityUsed;     //< used capacity
    MEMIMAGE_ADDR_T     capacityRsrv;     //< reserved capacity
    MEMIMAGE_ADDR_T     alreadyRead;      //< already read
    struct _MemoryEntry_s_*  prev;        //< prev entry in list
    struct _MemoryEntry_s_*  next;        //< next entry in list
} MemoryEntry_s;


/// memory image container  
typedef struct {
    MemoryEntry_s*      firstMemoryEntries;  //< first memory entries
    MemoryEntry_s*      lastMemoryEntries;   //< last memor entries
    size_t              numEntries;          //< number of entries 
} MemoryImage_s;


/**********************
 GLOBAL FUNCTIONS
**********************/

/// @brief initialize empty memory image 
/// @param image          pointer to memory image
void MemoryImage_init(MemoryImage_s* image);

/// @brief release memory image buffer 
/// @param image          pointer to memory image
void MemoryImage_free(MemoryImage_s* image);

/// @brief add byte at specified address in memory image. If address already exists, overwrite content
/// @param      image     pointer to memory image
/// @param[in]  address   address to add entry at
/// @param[in]  data      data to add
/// @return operation successful
bool MemoryImage_addData(MemoryImage_s* image, const MEMIMAGE_ADDR_T address, const uint8_t data);

#ifdef __cplusplus
}
#endif

#endif // _IMAGE_H_

// end of file
